package nl.tue.be.ds.duraark.bSDD.dump.alternatives;

import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import nl.tue.be.ds.duraark.bSDD.dump.ConSearchPerTermCallable;

import com.sun.jersey.api.client.UniformInterfaceException;

public class ConSearchProcessor {
	
	private int MaxThreadNum;
	private int MaxSearchTermLength;
	private Integer taskNum;

	public ConSearchProcessor(int maxThreadNum, int maxSearchTermLength) {
		super();
		MaxThreadNum = maxThreadNum;
		MaxSearchTermLength = maxSearchTermLength;
	}
	
	private void postSearchCallPerTerm(String searchTerm, CompletionService<Integer> completionService){

		ConSearchPerTermCallable callable = new ConSearchPerTermCallable(searchTerm);
		completionService.submit(callable);
	}
	
	public void postSearchCallPerTermPattern(String searchTerm, CompletionService<Integer> completionService){
			
		System.out.println("pattern search Term : " + searchTerm + " Term length : " + searchTerm.length());
		ConSearchPerTermPatternCallable callable = new ConSearchPerTermPatternCallable(searchTerm);
		completionService.submit(callable);
	}
	
	public Integer searchProcess(){
		taskNum = 0;
		Integer sum = 0;
		ExecutorService threadPool = Executors.newFixedThreadPool(MaxThreadNum);
		CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool);
		
		for (char ch1 = 'a'; ch1 <= 'z'; ch1++) {
			String searchTerm = Character.toString(ch1);
			postSearchCallPerTermPattern(searchTerm, completionService);
			taskNum ++;
		}
		
		for (Integer i = 0; i <= taskNum; i++){
			System.out.println("taskNum : " + taskNum);
			try {
				sum = sum + completionService.take().get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				exceptionProcess(e, completionService);
			}
		}	
		
		threadPool.shutdown();
		return sum;
	}
	
	
	private void exceptionProcess(ExecutionException e, CompletionService<Integer> completionService){
		
		if (e.getCause().getCause() instanceof UniformInterfaceException) {
			UniformInterfaceException uifException = (UniformInterfaceException) e.getCause().getCause();
			
			switch (uifException.getResponse().getStatus()) {
			case 500:
				String failedSearchTerm = e.getCause().getMessage();

				if (failedSearchTerm.length() <= MaxSearchTermLength){
					postSearchCallPerTerm(failedSearchTerm, completionService);
					taskNum ++;
				}

				if (failedSearchTerm.length() < MaxSearchTermLength){
					for (char ch = 'a'; ch <= 'z'; ch++) {
						String newSearchTerm = failedSearchTerm + Character.toString(ch);
						postSearchCallPerTermPattern(newSearchTerm, completionService);
						taskNum ++;
					}
				}
				break;
			case 503:
				String unavailableSearchTerm = e.getCause().getMessage();
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				postSearchCallPerTermPattern(unavailableSearchTerm, completionService);
				taskNum ++;
				break;
			default:
				e.printStackTrace();
			}
		}else {
			e.printStackTrace();
		}
	}

	
}
